#!/usr/local/bin/python
# -*- coding: utf-8 -*

# Libraries
import serial
import socket

serialPort=0 # Can use: 0; COM?, /dev/ttyUSB?
serverPort=0
serverURL=""

class dongleTCP:
	def __init__(self, RS232, url, port):
		self.SERVER = socket.socket()
		self.RS232 = RS232
		self.AUTHENTICATED = 0
		try:
			self.SERVER.connect((url, int(port)))
			self.CONNECTED = 1
		except Exception:
			print ("[-] Unable to connect to Server: "+url+":"+port)
			self.CONNECTED = 0			
	def authServer(self):					
		def authDeskey(deskeyData):	# First Action - Receives 3-Deskey to be XORed by Tuner
			if (deskeyData.__len__() == 66):
				try:
					print "[*] Starting Server Authentication..."
					self.SERVER.send(deskeyData) # Send 3-Deskey XORed (66 Bytes)
					self.RS232.writeData("<S>"+self.SERVER.recv(26)+"\x00") # Receive Login Request (26 Bytes)
					return 1
				except Exception:
					print "[-] Error on start Server Autenthication"
					return 0
			else:
				return 0
		def authLogin(loginData):	# Second Action - Sends Login and Password on Authentication Request
			if(loginData.__len__() == 26) :
				try:
					print "[*] Authenticating..."
					self.SERVER.send(loginData) # Send Login and Pass (26 Bytes)
					self.RS232.writeData("<S>"+self.SERVER.recv(50)+"\x00") # Confirm Authentication on Server (50 Bytes)
					return 1
				except Exception:
					print "[-] Error on Authentication: Check Login and Password"
					return 0
			else:
				return 0	
		AUTHSTATUS_DESKEY = 0
		AUTHSTATUS_LOGIN = 0
		self.RS232.writeData("<S>"+self.SERVER.recv(14)+"\x00") # Receive 3-Deskey (14 Bytes)
		while 1:
			buffer = self.RS232.readData()
			if (buffer):
				if (AUTHSTATUS_DESKEY == 0):
					if (ord(buffer[2:3]) == 66):
						AUTHSTATUS_DESKEY = authDeskey(buffer[3:-2])
				if (AUTHSTATUS_LOGIN == 0):
					if (ord(buffer[2:3]) == 26):
						AUTHSTATUS_LOGIN = authLogin(buffer[3:-2])
				else:
					print "[+] Authenticated with Success"
					return 1				
	def syncServer(self):
		buffer = self.RS232.readData()
		try:
			self.SERVER.send(buffer[3:-2])
			self.RS232.writeData("<S>"+self.SERVER.recv(1024)+"\x00")
		except Exception:
			"[-] Server Communication Error"

class dongleSerial:
	controlCodes = {
		"\x06\x00\x06"		:	"<S>",					# Finish Comm
		"\x0d\x00\x0d"		:	"<E>",					# Starts Comm
		"WR"				:	"<S>",					# Wait Response
		"RF"				:	"<SEMU1.0.0.0>",		# Dongle Version
		"RD"				:	"<S0>",					# Protocol Type (0-Static; 1-DHCP; 2-PPPoE)
		"RI"				:	"<S255.255.255.255>",	# Dongle IP Address
		"RP"				:	"<S0>",					# Dongle Port
		"RS"				:	"<S255.255.255.255>",	# Dongle Subnet Mask Address
		"RG"				:	"<S255.255.255.255>",	# Dongle Gateway Address
		"RU"				:	"<S1>",					# DNS (0-OFF; 1-ON;)
		"RV"				:	"<S255.255.255.255>",	# DNS Primary Address
		"RY"				:	"<S>",					#?
		"RZ"				:	"<S>",					#?
		"WT"				:	"<S>",					#?
		"WU"				:	"<S>",					#?
		"WV"				:	"<S>",					#?
		"WW"				:	"<S>",					# Server Ip Address
		"WN"				:	"<S>",					# Server Port
	}
	def __init__(self):
		global serialPort
		self.SYNC = 0
		try:
			self.RS232 = serial.Serial(serialPort)
			self.CONNECTED = 1
		except Exception:
			print ("[-] Unable to Open Serial Port")
			self.CONNECTED = 0
		if (self.CONNECTED):
			self.RS232.baudrate = 57600
			self.RS232.parity = serial.PARITY_NONE # Configure to Parity None
			self.RS232.bytesize = serial.EIGHTBITS # Configure to bytesize 8 Bits
			self.RS232.setDTR(True) # Set DTR Flowcontrol ON
			self.RS232.setRTS(True) # Set RTS Flowcontrol ON
			self.RS232.setXON(True) # Set XON Flowcontrol ON
	def readData(self):	
		bufferData = self.RS232.read(2) # Read First 2 Bytes
		if (bufferData[1:2] != "\x00"):
			data = self.RS232.read()
			while ord(data) != 62: # Bufferize and stops if Char == ">"(62)
				bufferData += data
				data = self.RS232.read()
			bufferData+=data
		else:
			bufferData+=self.RS232.read()
			while (bufferData[3:-1].__len__() < ord(bufferData[2:3])+1):
				bufferData += self.RS232.read()
		if not(self.controlData(bufferData)):
			return bufferData
	def writeData(self, msg):
		self.RS232.write(msg) # Write data on Serial
	def controlData(self, command):
		global serverURL
		global serverPort
		if (command[1:3] == "WW")	: # Case call Server IP Address command
			serverURL = command[3:-1]; 
			self.writeData(self.controlCodes[command[1:3]]); 	
		elif (command[1:3] == "WN")	: # Case call Server Port command
			serverPort = command[3:-1]; 
			self.writeData(self.controlCodes[command[1:3]]);
		else:
			if (self.controlCodes.has_key(command[1:3])):
				self.writeData(self.controlCodes[command[1:3]])
			else:
				if (command[1:-1] == "\x05\x00\x05"):
					if (self.SYNC!=1):
						print "[*] Connecting to Server..."
						self.SYNC = 1
				elif (command[1:-1] == "\x06\x00\x06"):
					self.writeData(self.controlCodes[command[1:-1]])
					print "[*] Ending Comunnication..."
					self.SYNC = 0
				elif (command[1:-1] == "\x0d\x00\x0d"):
					self.writeData(self.controlCodes[command[1:-1]])
					print "[*] Starting Comunnication..."
				else:
					return 0
		return 1
	
if __name__ == "__main__":
	xEmu=dongleSerial()
	while (xEmu.CONNECTED):
		while (xEmu.SYNC!=1):
			xEmu.readData()	
		xServer=dongleTCP(xEmu, serverURL, serverPort)
		while (xServer.CONNECTED):
			if not(xServer.AUTHENTICATED):
				xServer.AUTHENTICATED = xServer.authServer()
			else:
				while (xEmu.SYNC == 1):
					xServer.syncServer()	
				xServer.CONNECTED = 0
